package com.atguigu.lease.web.app.service.impl;

import com.atguigu.lease.common.constant.RedisConstant;
import com.atguigu.lease.common.exception.StgyException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import com.atguigu.lease.common.utils.JwtUtil;
import com.atguigu.lease.common.utils.VerifyCodeUtil;
import com.atguigu.lease.model.entity.UserInfo;
import com.atguigu.lease.model.enums.BaseStatus;
import com.atguigu.lease.web.app.service.LoginService;
import com.atguigu.lease.web.app.service.SmsService;
import com.atguigu.lease.web.app.service.UserInfoService;
import com.atguigu.lease.web.app.vo.user.LoginVo;
import com.atguigu.lease.web.app.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements LoginService {
  @Autowired private StringRedisTemplate redisTemplate;
  @Autowired private SmsService smsService;
  @Autowired private UserInfoService userInfoService;

  @Override
  public boolean getSMSCode(String phone) {
    // 1.检查手机号码是否为空
    if (!StringUtils.hasText(phone)) {
      throw new StgyException(ResultCodeEnum.APP_LOGIN_PHONE_EMPTY);
    }

    // 2. 检查Redis中是否已经存在该手机号码的key
    String key = RedisConstant.APP_LOGIN_PREFIX + phone;
    boolean hasKey = redisTemplate.hasKey(key);
    if (hasKey) {
      // 若存在，则检查其存在的时间
      Long expire = redisTemplate.getExpire(key, TimeUnit.SECONDS);
      if (RedisConstant.APP_LOGIN_CODE_TTL_SEC - expire
          < RedisConstant.APP_LOGIN_CODE_RESEND_TIME_SEC) {
        // 若存在时间不足一分钟，响应发送过于频繁
        throw new StgyException(ResultCodeEnum.APP_SEND_SMS_TOO_OFTEN);
      }
    }
    // 3.发送短信，并将验证码存入Redis
    String verifyCode = VerifyCodeUtil.getVerifyCode(6);
    smsService.sendCode(phone, verifyCode);
    redisTemplate
        .opsForValue()
        .set(key, verifyCode, RedisConstant.APP_LOGIN_CODE_TTL_SEC, TimeUnit.SECONDS);

    return true;
  }

  @Override
  public String login(LoginVo loginVo) {
    // 1.检查手机号码是否为空
    if (!StringUtils.hasText(loginVo.getPhone())) {
      throw new StgyException(ResultCodeEnum.APP_LOGIN_PHONE_EMPTY);
    }
    // 2.检查验证码是否为空
    if (!StringUtils.hasText(loginVo.getCode())) {
      throw new StgyException(ResultCodeEnum.APP_LOGIN_CODE_EMPTY);
    }
    // 3.根据手机号码查询redis中是否有验证码
    String key = RedisConstant.APP_LOGIN_PREFIX + loginVo.getPhone();
    String verifyCode = redisTemplate.opsForValue().get(key);
    if (!StringUtils.hasText(verifyCode)) {
      // 查询到的验证码为空 响应验证码过期
      throw new StgyException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_EXPIRED);
    }
    if (!verifyCode.equals(loginVo.getCode())) {
      // 验证码不正确
      throw new StgyException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_ERROR);
    }
    // 根据手机号码查询用户信息 若为空则创建新用户 将信息保存到数据库
    UserInfo dbUserInfo =
        userInfoService.getOne(
            Wrappers.lambdaQuery(UserInfo.class).eq(UserInfo::getPhone, loginVo.getPhone()));
    if (dbUserInfo == null){
      // 查询结果为空 创建新用户
      dbUserInfo = new UserInfo();
      dbUserInfo.setPhone(loginVo.getPhone());
      dbUserInfo.setNickname("用户" + loginVo.getPhone().substring(0,4));
      dbUserInfo.setStatus(BaseStatus.ENABLE);
      dbUserInfo.setPassword("123456");
      dbUserInfo.setAvatarUrl("https://img0.baidu.com/it/u=499887270,3457043283&fm=253&fmt=auto&app=138&f=PNG?w=500&h=590");
      // 保存到数据库
      userInfoService.save(dbUserInfo);
    }else {
      // 用户已存在 判断用户状态是否被禁用
      if (dbUserInfo.getStatus() == BaseStatus.DISABLE) {
        // 禁用状态 响应用户被禁用
        throw new StgyException(ResultCodeEnum.ADMIN_ACCOUNT_DISABLED_ERROR);
      }
    }
    // 创建token并返回
    return JwtUtil.createToken(dbUserInfo.getId(), loginVo.getPhone());

  }

  @Override
  public UserInfoVo getUserInfo(Long userId) {
    UserInfo userInfo = userInfoService.getById(userId);
    UserInfoVo userInfoVo = new UserInfoVo(userInfo.getNickname(), userInfo.getAvatarUrl());
    return userInfoVo;
  }
}
